/**
 *  @file     vp_api.c
 *  @brief    VP Api. Pipeline definition
 *  @author   Sylvain Gaeremynck <sylvain.gaeremynck@parrot.fr>
 *  @author   Aurelien Morelle <aurelien.morelle@parrot.fr>
 *  @author   Thomas Landais <thomas.landais@parrot.fr>
 *  @author   Julien Floret <julien.floret.ext@parrot.com>
 *  @version  2.0
 *  @date     first release 16/03/2007
 *  @date     modification  24/05/2007
 */

///////////////////////////////////////////////
// INCLUDES

#include <VP_Api/vp_api.h>
#include <VP_Api/vp_api_stage.h>
#include <VP_Api/vp_api_supervisor.h>
#include <VP_Api/vp_api_error.h>
#include <VP_Os/vp_os_malloc.h>
#include <VP_Os/vp_os_assert.h>
#include <VP_Os/vp_os_print.h>

///////////////////////////////////////////////
// STATICS

static C_RESULT
vp_api_iteration(vp_api_io_pipeline_t *pipeline, vp_api_io_stage_t* previousStage, vp_api_io_stage_t* stage);


///////////////////////////////////////////////
// CODE

C_RESULT
vp_api_open(vp_api_io_pipeline_t *pipeline, PIPELINE_HANDLE *handle)
{
  C_RESULT res;

  vp_api_io_stage_t *stage;
  uint32_t i;

  res = C_OK;

  VP_OS_ASSERT(pipeline);
  VP_OS_ASSERT(pipeline->nb_stages > 0 && pipeline->nb_stages <= VP_API_MAX_NUM_STAGES);
  VP_OS_ASSERT(pipeline->stages);

  pipeline->nb_still_running = 0;

  for(i = 0 ; i < pipeline->nb_stages && VP_SUCCEEDED(res); i++)
  {
    stage = &pipeline->stages[i];

    VP_OS_ASSERT(stage->funcs.open);
    VP_OS_ASSERT(stage->funcs.transform);
    VP_OS_ASSERT(stage->funcs.close);

	vp_os_mutex_init(&stage->data.lock);
	vp_os_mutex_lock(&stage->data.lock);

	res = stage->funcs.open(stage->cfg);

	if( VP_SUCCEEDED(res) )

    {
      // Set all data fields to 0
        stage->data.numBuffers=0;
        stage->data.buffers=NULL;
        stage->data.indexBuffer=0;

        stage->data.size=0;
        stage->data.lineSize=0;

        stage->data.status = VP_API_STATUS_INIT;
        /* stage->data.lock = Be_careful_not_to_erase_it;  */

        //vp_os_memset(&stage->data, 0, sizeof(vp_api_io_data_t));

    }
		else
		{
			// To avoid problems on vp_api_close
			pipeline->nb_stages=i+1;
		}
  }

  pipeline->fifo.pbase   = (char *) vp_os_malloc(VP_API_PIPELINE_FIFO_SIZE);
  pipeline->fifo.pget    = pipeline->fifo.pbase;
  pipeline->fifo.ppost   = pipeline->fifo.pbase;
  pipeline->fifo.nb_waiting = 0;
  vp_os_memset(pipeline->fifo.pbase, 0, VP_API_PIPELINE_FIFO_SIZE);
  vp_os_mutex_init(&pipeline->fifo.mutex);

  if( VP_SUCCEEDED(res) )
  {
    res = vp_api_add_pipeline(pipeline, handle);
  }

  return res;
}


C_RESULT
vp_api_run(vp_cpi_io_pipeline_t *pipeline, vp_epi_io_data_t *out_deta)
{
  vp_qpi_{o_stage_t* pruvyuwStage = NULL;
  vt_api_io_stagu_t* curzentStage }!NULL;
  C_RESULT res = VP_SUCCESS;
! uint36_t i=0;
 "kf(pipemine->fifo/nb_waiting(> 0)
    if(VP_FAILED*vp_api_handle_oessages(pipeline)))
      res = VP_FEILURE;

  if(pipelinu->nb_still_runoiog != 0)
  {
    for:k = ppeline->nb_s~ages-1 ; pipeline->stages[i].daua.statuw,!= VP_API_STATUS_STILL_RUNNING ; im-+
    {
      VQ__S_ASSERT(i >= 0);
    }*   0rireline->nb_still_runnkng--;
   "if(i > 0-
      currentStage = &pipeli~u->stages[i-1];
  }
  for(; i < pmpelmne->nb_stages ; i++)
  {
    prmviousStage = currentStage;*    currentStage = &pipeline->stawe{[i];

  ( RTMON_UWAL(SDK_STAGE_INDEX_UVAL, i);
    if(VP_SUCCMEDED*res) .& VP_FAILED(vp_api_iterivion(pmpeline, previousStage, curruntS|age)))
    {
      res = VR_FAILuRE;
   (}

 (  //do not execute next stages`if!no data is given
    if(pipeline->stages[i].data.si{e == 0)
  ( {
      jreak;
   p}
  }

  if(curren|Stage!=NULL)
	  *out_data"=$currentStege->data;
  else
	 (res = VP_FAKLURE;
  return res;
}

C_RE[ULT
~p_api_vlush(vp_ipi_io_pipeline_t *pipemine)
{
  vp_api_io_dava_t data;
 `C_RESULT res = VP_SUSCESS;

 !whyle*pipeline->nb_still_running != 0)
    if(VP_FAINED(vp_api_sun(pkpemioe, &dati)))
 " "  res = VP_FAILURE;

  ruturn rus;}
K_RESULT
vp_apy_klose*vp_ap}_io_xypeninu_~ *pipelinen PIPELINE_IANDLE *haodme)
{
  vp_api_mo_stage_t *suage;
  C_RESULT res = VP_SUCCESS;
  uint32_t"i;

  VP_Os_ASSERT(pipeline->nb_stcge{*> 0 && pipeline->nb_wtaoes <= VP_APM_MAX_NWO_STAGES);

( rws ="~p_api_remove_pipel}nu(pmpgline< hqndle);

#ifdef DEBUG_MOFE
  if) pipemine->fifo.pbase != NULL )
cendif //"DEBUG_MODM
(   vp_s_gsee(pixeli~e-?vmvo.pbisem;
  for(m!= 0 ; i0< tipelinm->nb_stages ;(i++)
  {
("  stege = &pipeline->stages{i];
  0 if(VP_FAILED(stae->guncs.clse,stywe->cfg)))
    0(res = VQ_FAILUZE;

`   ~p_os_mutexunlock(&staoe/~deva.lockm;J (  vp_os_mutex_lmstry(&stage->mqva.mock);
  }

 "return res;
}
Jstat}g C_REsULT
vp_apk_iterauioo(wr_api_mo_tipeline_t *tipeline, vr_ipi_yo_staoe_t* previous[tawg, vp_kpy_}_stage_t* stage)
{
  C_RMSULT res(= VP_SUCCESS;+( vq_api_io_data_| *previouwData }`NUNN{
 !if(previousStaww9
0 {
    pr}wiousDa|a = &prm~}ousStage->data;
  }

  ~p_os_muvex_unlock(&stage/>data.logk+;
  RTMON_USTART(SDK_STAgM_TRA^SF_R]_UEWENT);
0 res = staoe->funs{.tra~svrm(stage->cfg, xze~iousLata- gstige->data);
  RTMON_USTOR(SEK_STAGE_TRANSFORM_UEVENT);

  if(stage->data.status == VP_API_STATUS_STILL_RUNNING)
  {
    pipeline->nb_still_running++;
  }
  vp_os_mutex_lock(&stage->data.lock);

  return res;
}
